# coding=utf8
__author__ = 'lijian'
import logging
import datetime
from utils import byteUtil
from utils import bcdUtil
import rtu

import config
import lamp
import struct


# 终端上行通信口通信参数设置
def fn_1(dataUnit):
    uplink = config.uplink

    raw = dataUnit.rawData

    bs = raw[0:2]
    bs[1] = bs[1] & 0xf

    uplink["slaveTimeout"] = byteUtil.decodeShort(bs)
    uplink["retry"] = raw[1] >> 4
    con = raw[2]
    uplink["heartbeatCycle"] = raw[3]

    initiative = uplink["initiative"]

    initiative["realTime"] = con & 1
    initiative["history"] = (con >> 1) & 1
    initiative["event"] = (con >> 2) & 1

    config.updateUplink()

    return True


# 主站IP地址和端口
def fn_2(dataUnit):
    data = dataUnit.rawData
    ipRaw = [data[0], data[1], data[2], data[3]]
    port = byteUtil.decodeShort(data[4:])

    end = data.index(0, 6)
    apn = struct.pack('B' * len(data[6:end]), *data[6:end])
    ip = "%s.%s.%s.%s" % (str(ipRaw[0]), str(ipRaw[1]), str(ipRaw[2]), str(ipRaw[3]))

    config.updateNetwork(ip, port, apn)
    return True


# 终端事件记录配置设置
def fn_3(dataUnit):
    raw = dataUnit.rawData

    validity = raw[0:8]
    importance = raw[8:16]
    initiativeReport = raw[16:24]

    index = 0
    for i in range(8):
        byte = validity[i]
        for k in range(8):
            value = (byte >> k) & 1
            event = config.eventConfig[index]
            event["validity"] = bool(value)
            index += 1

    index = 0
    for i in range(8):
        byte = importance[i]
        for k in range(8):
            value = (byte >> k) & 1
            event = config.eventConfig[index]
            event["importance"] = bool(value)
            index += 1

    index = 0
    for i in range(8):
        byte = initiativeReport[i]
        for k in range(8):
            value = (byte >> k) & 1
            event = config.eventConfig[index]
            event["initiative"] = bool(value)
            index += 1

    config.updateEventRecordConfig()

    return True


# 设备基本信息
def fn_4(dataUnit):
    raw = dataUnit.rawData

    info = {}

    info["boxNo"] = tuple(raw[0:6])
    info["address"] = tuple(raw[6:14])

    info["longitude"] = bcdUtil.bcdToNumber(raw[14:19])
    info["latitude"] = bcdUtil.bcdToNumber(raw[19:24])

    info["lampEnable"] = True if raw[24] != 0 else False
    info["frequency"] = byteUtil.decodeShort(raw[25:27])

    config.updateBaseInfo(info)

    return True


# 终端事件检测配置参数
def fn_5(dataUnit):
    raw = dataUnit.rawData
    config.eventDetectionConfig["commFailTime"] = raw[0]
    config.eventDetectionConfig["routeFailTime"] = raw[1]
    config.eventDetectionConfig["lampOnDelay"] = raw[2]
    config.eventDetectionConfig["lampOffDelay"] = raw[3]
    config.eventDetectionConfig["lampCurrentDelay"] = raw[4]

    config.updateEventDetectionConfig()

    return True


# 单灯事件检测配置参数
def fn_6(dataUnit):
    raw = dataUnit.rawData
    config.lampThresholdConfig["maxCurrentThreshold"] = raw[0]
    config.lampThresholdConfig["maxCurrentRecover"] = raw[1]
    config.lampThresholdConfig["minCurrentThreshold"] = raw[2] / 1000.0
    config.lampThresholdConfig["minCurrentRecover"] = raw[3] / 1000.0
    config.lampThresholdConfig["lowPFThreshold"] = byteUtil.decodeA5(raw[4:6])
    config.lampThresholdConfig["lowPFRecover"] = byteUtil.decodeA5(raw[6:8])
    config.lampThresholdConfig["breakdownCurrentThreshold"] = raw[8] / 1000.0
    config.lampThresholdConfig["breakdownCurrentRecover"] = raw[9] / 1000.0
    config.lampThresholdConfig["burnCurrentThreshold"] = raw[10] / 1000.0
    config.lampThresholdConfig["burnCurrentRecover"] = raw[11] / 1000.0

    config.updateLampThresholdConfig()

    return True


# 终端级联通信参数
def fn_7(dataUnit):
    return None


# 控制器开关灯时间参数
def fn_9(dataUnit):
    raw = dataUnit.rawData

    if not rtu.action.writeTimeSheet(dataUnit.rawData):
        return False
    else:

        month = raw[0]
        day = raw[1]
        dayCount = byteUtil.decodeShort(raw[2:4])

        offset = 4
        records = []

        i = 0
        while i < dayCount:
            bcd = bcdUtil.bcdTohex(raw[offset:offset + 2])
            minute = bcd[0]
            hour = bcd[1]
            onTime = [hour, minute]
            offset += 2

            bcd = bcdUtil.bcdTohex(raw[offset:offset + 2])
            minute = bcd[0]
            hour = bcd[1]
            offTime = [hour, minute]
            offset += 2

            record = {
                "date": "%d-%d" % (month, day),
                "onTime": onTime,
                "offTime": offTime
            }

            records.append(record)
            month, day = rtu.manager.addDay(month, day)
            i += 1
            if month > 12:
                month = 1
                day = 1

        rtu.manager.replaceActions(records)

        return True


# 信息量检测间隔时间参数
def fn_11(dataUnit):
    raw = dataUnit.rawData

    tmp = raw[0:2]
    DI = bcdUtil.bcdToNumber(tmp)

    tmp = raw[2:5]
    AI = bcdUtil.bcdToNumber(tmp)

    tmp = raw[5:7]
    ammeter = bcdUtil.bcdToNumber(tmp)

    config.rtuDetectionInterval["DI"] = DI
    config.rtuDetectionInterval["AI"] = AI
    config.rtuDetectionInterval["ammeter"] = ammeter

    config.updateRtuDetectionInterval()

    return True


# 控制回路参数
def fn_12(dataUnit):
    byte = dataUnit.rawData[0]
    for i in range(8):
        config.rtuLoopParam["ctrlValid"][i] = (byte >> i) & 1

    byte = dataUnit.rawData[1]
    for i in range(8, 16):
        offset = i % 8
        config.rtuLoopParam["ctrlValid"][i] = (byte >> offset) & 1

    config.rtuLoopParam["saving"] = bool(dataUnit.rawData[2])
    config.rtuLoopParam["level"] = dataUnit.rawData[3]

    config.updateRtuLoopParam()

    return True


# 控制器、单灯分组自动控制参数
def fn_13(dataUnit):
    raw = dataUnit.rawData
    enable = raw[0]
    count = raw[1]

    group = lamp.manager.getGroup(dataUnit.PN)

    offset = 2
    for i in range(count):
        task = lamp.AutoCtrlTask()

        no = raw[offset]
        offset += 1
        task.no = no

        task.timeType = raw[offset]
        offset += 1

        task.ctrlType = raw[offset]
        offset += 1

        task.level = raw[offset]
        offset += 1

        task.relativeTime = raw[offset]
        offset += 1

        if task.timeType == 01:  # 绝对时间
            task.absoluteTime = bcdUtil.decodeDateTime(raw[offset:offset + 6])
        else:
            task.absoluteTime = datetime.datetime.strptime("1970-01-01", "%Y-%m-%d")

        offset += 6

        group.addAutoTasks(task)

    lamp.manager.saveAutoTasks()
    return True


# 集中器与单灯控制器关系参数设置
def fn_17(dataunit):
    raw = dataunit.rawData
    termNumber = raw[0]
    offset = 1
    termList = []
    for i in range(termNumber):
        deviceId = byteUtil.decodeShort(raw[offset:])
        enable = raw[offset + 2]

        bin = raw[offset + 3:offset + 3 + 8]
        number=byteUtil.decodeLong(bin)
        str="%012d"%(number)
        uid=[]
        for k in range(0,12,2):
            uid.append(int(str[k:k+2]))

        loopFlag = raw[offset + 11]
        poleNo = byteUtil.decodeInt(raw[offset + 12:offset + 16])

        offset += 16
        term = lamp.Term(deviceId, uid, enable, loopFlag, poleNo)
        termList.append(term)
    logging.debug("decode term count:%d" % len(termList))
    for term in termList:
        lamp.manager.addTerm(term)

    lamp.manager.saveLamps()

    return True


# 单灯控制器与灯具关系参数
def fn_18(dataUnit):
    pn = dataUnit.PN
    term = lamp.manager.findTermByDeviceId(pn)
    if not term:
        return False

    raw = dataUnit.rawData
    lampNumber = raw[0]
    offset = 1
    holderList = []
    for i in range(lampNumber):
        holderNo = byteUtil.decodeShort(raw[offset:offset + 2])
        enable = raw[offset + 2]
        lineNo = raw[offset + 3]
        phase = raw[offset + 4]
        loopNo = raw[offset + 5]

        holder = lamp.Holder(holderNo, enable, lineNo, phase, loopNo)
        offset += 6
        holderList.append(holder)

    logging.debug("decode holder count:%d" % len(holderList))
    for holder in holderList:
        term.addHolder(holder)

    lamp.manager.saveLamps()

    return True


# 单灯自动控制参数
def fn_19(dataUnit):
    raw = dataUnit.rawData
    enable = raw[0]
    count = raw[1]

    holder = lamp.manager.findHolder(dataUnit.PN)
    if not holder:
        return False

    offset = 2
    for i in range(count):
        task = lamp.AutoCtrlTask()

        no = raw[offset]
        offset += 1
        task.no = no

        task.timeType = raw[offset]
        offset += 1

        task.ctrlType = raw[offset]
        offset += 1

        task.level = raw[offset]
        offset += 1

        task.relativeTime = raw[offset]
        offset += 1

        if task.timeType == 01:  # 绝对时间
            task.absoluteTime = bcdUtil.decodeDateTime(raw[offset:offset + 6])
        else:
            task.absoluteTime = datetime.datetime.strptime("1970-01-01", "%Y-%m-%d")

        offset += 6
        holder.addAutoTasks(task)

    lamp.manager.saveAutoTasks()
    return True


# 单灯分组参数
def fn_20(dataUnit):
    term = lamp.manager.findTermByDeviceId(dataUnit.PN)
    if not term:
        return False

    raw = dataUnit.rawData
    count = raw[0]
    offset = 1
    for i in range(count):
        g = raw[offset]
        offset += 1

        term.addGroup(g)
    lamp.manager.saveLamps()

    return True


# 遥信量分类参数
def fn_25(dataUnit):
    count = dataUnit.rawData[0]
    point = dataUnit.rawData[1]

    offset = 2
    paramDict = {}
    for i in range(count):
        raw = dataUnit.rawData[offset:]
        data = {}
        data["type"] = raw[0]
        data["line"] = raw[1]
        data["phase"] = raw[2]

        paramDict[point] = data
        point += 1
        offset += 3

    rtu.manager.appendSignalType(paramDict)

    return True


# 模拟量分类限值参数
def fn_26(dataUnit):
    count = dataUnit.rawData[0]
    point = dataUnit.rawData[1]

    offset = 2
    paramDict = {}
    for i in range(count):
        raw = dataUnit.rawData[offset:]
        data = {}
        data["enable"] = raw[0]
        data["type"] = raw[1]
        data["line"] = raw[2]
        data["phase"] = raw[3]
        data["onUpperLimit"] = rtu.manager.decodeAnalogByPoint(point, raw[4:6])
        data["onLowerLimit"] = rtu.manager.decodeAnalogByPoint(point, raw[6:8])
        data["offUpperLimit"] = rtu.manager.decodeAnalogByPoint(point, raw[8:10])
        data["offLowerLimit"] = rtu.manager.decodeAnalogByPoint(point, raw[10:12])

        key = str(point)
        paramDict[key] = data
        point += 1
        offset += 12

    rtu.manager.appendAnalogLimitParam(paramDict)

    return True

